#include <stdlib.h>
#include <typeinfo>
#include "Arbre.h"
#include "Symbole.h"
#include "SymboleValue.h"
#include "Valeur.h"



////////////////////////////////////////////////////////////////////////////////
// NoeudSeqInst
////////////////////////////////////////////////////////////////////////////////

NoeudSeqInst::NoeudSeqInst() : tabInst() {
}

////////////////////////////////////////////////////////////////////////////////
Valeur* NoeudSeqInst::getValeur() {
    Valeur* valeur = new ValeurInt(1);
    for (unsigned int i=0; i<tabInst.size(); i++)
        valeur = tabInst[i]->getValeur();  // on evalue chaque instruction de la séquence
    return valeur; // par convention, resultat = valeur de la derniere instruction
}

////////////////////////////////////////////////////////////////////////////////
// void NoeudSeqInst::afficher(unsigned short indentation) {
//   Noeud::afficher(indentation);
//   cout << "Noeud - Sequence de " << tabInst.size() << " instruction(s)" << endl;
//   for (unsigned int i=0; i<tabInst.size(); i++)
//     tabInst[i]->afficher(indentation+1); // on affiche les fils en augmentant l'indentation
// }

////////////////////////////////////////////////////////////////////////////////
int NoeudSeqInst::getSize() {
    return tabInst.size();
}

////////////////////////////////////////////////////////////////////////////////
void NoeudSeqInst::ajouteInstruction(Noeud* instruction) {
    tabInst.push_back(instruction);
}

void NoeudSeqInst::Accept (NoeudVisitor& visitor) {
    if (typeid(visitor) == typeid(AfficherVisitor)) {
        visitor.IncresIndentation();
		visitor.VisitNoeudSeqInst(this);
		for (unsigned int i=0; i<tabInst.size(); i++)
			tabInst[i]->Accept(visitor); // on affiche les fils en augmentant l'indentation
        visitor.DecresIndentation();
    }
    else {
	for (unsigned int i=0; i<tabInst.size(); i++)
		tabInst[i]->Accept(visitor); // on affiche les fils en augmentant l'indentation
	visitor.VisitNoeudSeqInst(this);
    }
      
}





////////////////////////////////////////////////////////////////////////////////
// NoeudSi
////////////////////////////////////////////////////////////////////////////////

NoeudSi::NoeudSi(Noeud* expbool, Noeud* seqInst, Noeud* siSuivant) {
    this->expBool=expbool;
    this->seqInst=seqInst;
    this->siSuivant=siSuivant;
}

////////////////////////////////////////////////////////////////////////////////
Valeur* NoeudSi::getValeur() {
    Valeur* valeur  = new ValeurInt(0); //
    if (((ValeurInt*)expBool->getValeur())->getValeur() == 1) valeur = seqInst->getValeur();
    if (siSuivant != NULL) siSuivant->getValeur();
//  ((SymboleValue*)variable)->setValeur(valeur); // on affecte la variable
    return valeur; // par convention, une affectation a pour valeur la valeur affectée
}

////////////////////////////////////////////////////////////////////////////////
// void NoeudSi::afficher(unsigned short indentation) {
//   Noeud::afficher(indentation);
//   cout << "Noeud - Si" << endl;
//   expBool->afficher(indentation+1);   // on affiche variable et expression
//   seqInst->afficher(indentation+1); // en augmentant l'indentation
//   if (siSuivant != NULL)
// 	  siSuivant->afficher(indentation+1); // en augmentant l'indentation
// }

void NoeudSi::Accept (NoeudVisitor& visitor) {
    if (typeid(visitor) == typeid(AfficherVisitor)) {
			visitor.IncresIndentation();
		visitor.VisitNoeudSi(this);
		expBool->Accept(visitor);
		seqInst->Accept(visitor);
		if (siSuivant != NULL)
			siSuivant->Accept(visitor);
		visitor.DecresIndentation();
    }
    else {
		expBool->Accept(visitor);
		seqInst->Accept(visitor);
		visitor.VisitNoeudSi(this);
		if (siSuivant != NULL)
			siSuivant->Accept(visitor);
    }
}



////////////////////////////////////////////////////////////////////////////////
// NoeudPour
////////////////////////////////////////////////////////////////////////////////

NoeudPour::NoeudPour(Noeud* aff, Noeud* affDroite, Noeud* expbool, Noeud* seqInst) {
    this->expBool=expbool;
    this->seqInst=seqInst;
    this->aff=aff;
    this->affDroite=affDroite;
}

////////////////////////////////////////////////////////////////////////////////
Valeur* NoeudPour::getValeur() {
    Valeur* valeur = new ValeurInt(0); // =
//  ((SymboleValue*)variable)->setValeur(valeur); // on affecte la variable
    for (aff->getValeur();((ValeurInt*)expBool->getValeur())->getValeur(); affDroite->getValeur())
        valeur = seqInst->getValeur(); // on affiche les fils en augmentant l'indentation
    return valeur; // par convention, une affectation a pour valeur la valeur affectée
}

////////////////////////////////////////////////////////////////////////////////
// void NoeudPour::afficher(unsigned short indentation) {
//   Noeud::afficher(indentation);
//   cout << "Noeud - Pour" << endl;
//   aff->afficher(indentation+1);   // on affiche variable et expression
//   expBool->afficher(indentation+1);   // on affiche variable et expression
//   affDroite->afficher(indentation+1);   // on affiche variable et expression
//   seqInst->afficher(indentation+1); // en augmentant l'indentation
// }

void NoeudPour::Accept (NoeudVisitor& visitor) {
    if (typeid(visitor) == typeid(AfficherVisitor)) {
        visitor.IncresIndentation();
	visitor.VisitNoeudPour(this);
	aff->Accept(visitor);
	expBool->Accept(visitor);
	affDroite->Accept(visitor);
	seqInst->Accept(visitor);
	visitor.DecresIndentation();
    }
    else {
	aff->Accept(visitor);
	expBool->Accept(visitor);
	affDroite->Accept(visitor);
	seqInst->Accept(visitor);
	visitor.VisitNoeudPour(this);
    }
}



////////////////////////////////////////////////////////////////////////////////
// NoeudTantQue
////////////////////////////////////////////////////////////////////////////////

NoeudTantQue::NoeudTantQue(Noeud* expbool, Noeud* seqInst) {
    this->expBool=expbool;
    this->seqInst=seqInst;
}

////////////////////////////////////////////////////////////////////////////////
Valeur* NoeudTantQue::getValeur() {
    Valeur* valeur = new ValeurInt(0); // = 
    while (((ValeurInt*)expBool->getValeur())->getValeur() == 1) {
        valeur = seqInst->getValeur();
    }
//  ((SymboleValue*)variable)->setValeur(valeur); // on affecte la variable
    return valeur; // par convention, une affectation a pour valeur la valeur affectée
}

////////////////////////////////////////////////////////////////////////////////
// void NoeudTantQue::afficher(unsigned short indentation) {
//   Noeud::afficher(indentation);
//   cout << "Noeud - TantQue" << endl;
//   expBool->afficher(indentation+1);   // on affiche variable et expression
//   seqInst->afficher(indentation+1); // en augmentant l'indentation
//
// }

void NoeudTantQue::Accept (NoeudVisitor& visitor) {
    if (typeid(visitor) == typeid(AfficherVisitor)) {
        visitor.IncresIndentation();
		visitor.VisitNoeudTantQue(this);
		expBool->Accept(visitor);
		seqInst->Accept(visitor);
        visitor.DecresIndentation();
    }
    else {
	expBool->Accept(visitor);
	seqInst->Accept(visitor);   
	visitor.VisitNoeudTantQue(this);
    }
}


////////////////////////////////////////////////////////////////////////////////
// NoeudRepeter
////////////////////////////////////////////////////////////////////////////////

NoeudRepeter::NoeudRepeter(Noeud* expbool, Noeud* seqInst) {
    this->expBool=expbool;
    this->seqInst=seqInst;
}

////////////////////////////////////////////////////////////////////////////////
Valeur* NoeudRepeter::getValeur() {
    Valeur* valeur; // = new ValeurInt(1);
    do {
        valeur = seqInst->getValeur();
    }
    while (((ValeurInt*)expBool->getValeur())->getValeur());
//  ((SymboleValue*)variable)->setValeur(valeur); // on affecte la variable
    return valeur; // par convention, une affectation a pour valeur la valeur affectée
}

////////////////////////////////////////////////////////////////////////////////
// void NoeudRepeter::afficher(unsigned short indentation) {
//   Noeud::afficher(indentation);
//   cout << "Noeud - Repeter" << endl;
//   seqInst->afficher(indentation+1); // en augmentant l'indentation
//   expBool->afficher(indentation+1);   // on affiche variable et expression
// }

void NoeudRepeter::Accept (NoeudVisitor& visitor) {
    if (typeid(visitor) == typeid(AfficherVisitor)) {
        visitor.IncresIndentation();
		visitor.VisitNoeudRepeter(this);
		expBool->Accept(visitor);
		seqInst->Accept(visitor);
        visitor.DecresIndentation();
    }
    else {
	  expBool->Accept(visitor);
	  seqInst->Accept(visitor);      
	  visitor.VisitNoeudRepeter(this);      
    }
}

////////////////////////////////////////////////////////////////////////////////
// NoeudAffectation
////////////////////////////////////////////////////////////////////////////////

NoeudAffectation::NoeudAffectation(Noeud* variable, Noeud* expression) {
    this->variable=variable;
    this->expression=expression;
}

////////////////////////////////////////////////////////////////////////////////
Valeur* NoeudAffectation::getValeur() {
    Valeur* valeur;
    valeur = expression->getValeur(); // on évalue l'expression
    ((SymboleValue*)variable)->setValeur(valeur); // on affecte la variable
    return valeur; // par convention, une affectation a pour valeur la valeur affectée
}

////////////////////////////////////////////////////////////////////////////////
// void NoeudAffectation::afficher(unsigned short indentation) {
//   Noeud::afficher(indentation);
//   cout << "Noeud - Affectation" << endl;
//   variable->afficher(indentation+1);   // on affiche variable et expression
//   expression->afficher(indentation+1); // en augmentant l'indentation
// }

void NoeudAffectation::Accept (NoeudVisitor& visitor) {
    if (typeid(visitor) == typeid(AfficherVisitor)) {
        visitor.IncresIndentation();
		visitor.VisitNoeudAffectation(this);
		this->variable->Accept(visitor);
		this->expression->Accept(visitor);
        visitor.DecresIndentation();
    }
    else {
      	this->variable->Accept(visitor);
	this->expression->Accept(visitor);
	visitor.VisitNoeudAffectation(this);
    }
}


////////////////////////////////////////////////////////////////////////////////
// NoeudDeclaration
////////////////////////////////////////////////////////////////////////////////

NoeudDeclaration::NoeudDeclaration(Noeud* variable, string type) {
    this->variable=variable;
    this->type=type;
    /*  if (type.getCategorie() == ENTIER)
      	this->variable().valeur = new ValeurInt(0);
      if (type == REEL)
      	this->variable().valeur = new ValeurFloat(0.0);
      if (type == CHAINE)
      	this->variable().valeur = new ValeurString("\0");
      if (type == CHAR)
      	this->variable().valeur = new Valeurchar('\0');
      this->variable->defini = false;*/
}

////////////////////////////////////////////////////////////////////////////////
Valeur* NoeudDeclaration::getValeur() {
    Valeur* valeur = new ValeurInt(1);
    // valeur = expression->getValeur(); // on évalue l'expression
    // ((SymboleValue*)variable)->setValeur(valeur); // on affecte la variable
    return valeur; // par convention, une affectation a pour valeur la valeur affectée
}

////////////////////////////////////////////////////////////////////////////////
// void NoeudAffectation::afficher(unsigned short indentation) {
//   Noeud::afficher(indentation);
//   cout << "Noeud - Affectation" << endl;
//   variable->afficher(indentation+1);   // on affiche variable et expression
//   expression->afficher(indentation+1); // en augmentant l'indentation
// }

void NoeudDeclaration::Accept (NoeudVisitor& visitor) {
    if (typeid(visitor) == typeid(AfficherVisitor)) {
        visitor.IncresIndentation();
		visitor.VisitNoeudDeclaration(this);
		this->variable->Accept(visitor);
		// this->type.Accept(visitor);
        visitor.DecresIndentation();
    }
    else {
	this->variable->Accept(visitor); 
	visitor.VisitNoeudDeclaration(this);
    }
}



////////////////////////////////////////////////////////////////////////////////
// NoeudLire
////////////////////////////////////////////////////////////////////////////////

NoeudLire::NoeudLire(Noeud* variable) {
    this->variable=variable;
}

////////////////////////////////////////////////////////////////////////////////
Valeur* NoeudLire::getValeur() {
    Valeur* valeur = new ValeurInt(0);;
//  ((SymboleValue*)variable)->setValeur(valeur); // on affecte la variable
// return valeur; // par convention, une affectation a pour valeur la valeur affectée
//  variable->afficher();
 //   cout << "getValeurLire" << endl;
  //  cout << (SymboleValue*)variable << endl;
    /* verifier le type de la variable, puis declarer une
     *  variable de se type. puis l'affecter a un Valeur**/
    if (((SymboleValue*)variable)->SymboleValue::getType() == "entier") {
    //	typeid(operandeGauche) == typeid(float)
        int val;
        cin >> val;
        valeur = new ValeurInt(val);
    }

    else if (((SymboleValue*)variable)->SymboleValue::getType() == "reel") {
        float val;
        cin >> val;
        valeur = new ValeurFloat(val);
    }
    else if (((SymboleValue*)variable)->SymboleValue::getType() == "chaine") {
        string val;
        cin >> val;
	string vaf = "\"";
	vaf = vaf + val;
	vaf = vaf + '\"';
        valeur = new ValeurString(vaf);
    }
    else if (((SymboleValue*)variable)->SymboleValue::getType() == "chara") {
	string val = "'0'";
	char vc;
	cin >> vc;
	val[1] = vc;
	valeur = new ValeurString(val);
    }
    else {
    	cout << "N'a pas lu" << endl;
    }
//     else if (typeid(variable) == typeid(char)) {
//         char val;
//         cin >> val;
//         valeur = new ValeurChar(val);
//     }

    // cout << "Nouvelle valeur ?" << endl;
    // cin >> valeur;
    ((SymboleValue*)variable)->setValeur(valeur); // on affecte la variable
    return valeur; // par convention, une affectation a pour valeur la valeur affectée
}

////////////////////////////////////////////////////////////////////////////////
// void NoeudLire::afficher(unsigned short indentation) {
//   Noeud::afficher(indentation);
//   cout << "Noeud - Lire" << endl;
//   variable->afficher(indentation+1);   // on affiche variable et expression
// //  expression->afficher(indentation+1); // en augmentant l'indentation
// }

void NoeudLire::Accept (NoeudVisitor& visitor) {
    if (typeid(visitor) == typeid(AfficherVisitor)) {
        visitor.IncresIndentation();
		visitor.VisitNoeudLire(this);
		variable->Accept(visitor);
        visitor.DecresIndentation();
    }
    else {
      	variable->Accept(visitor);
	visitor.VisitNoeudLire(this);
    }
}

////////////////////////////////////////////////////////////////////////////////
// NoeudEcrire
////////////////////////////////////////////////////////////////////////////////

NoeudEcrire::NoeudEcrire(Noeud* expression) {
    this->expression=expression;
}

////////////////////////////////////////////////////////////////////////////////
Valeur* NoeudEcrire::getValeur() {
    Valeur* valeur;
    if (((SymboleValue*)expression)->SymboleValue::getType() == "entier") {
	cout << ((ValeurInt*)((SymboleValue*)expression)->getValeur())->getValeur();
    }

    else if (((SymboleValue*)expression)->SymboleValue::getType() == "reel") {
	cout << ((ValeurFloat*)((SymboleValue*)expression)->getValeur())->getValeur();
    }
    else if (((SymboleValue*)expression)->SymboleValue::getType() == "chaine") {
	string chaine = ((ValeurString*)((SymboleValue*)expression)->getValeur())->getValeur();
	for (unsigned int i=1;i<chaine.size()-1;i++) {
	  if (chaine[i] == '\\' && chaine[i+1] == 'n') {
	    cout << endl;
	    i++;
	  }
	  else if (chaine[i] == '\\' && chaine[i+1] == '\"') {
	    cout << '\"';
	    i++;
	  }
	  else {
	    cout << chaine[i];
	  }
	}
	  
    }
    else if (((SymboleValue*)expression)->SymboleValue::getType() == "chara") {
	cout << ((ValeurString*)((SymboleValue*)expression)->getValeur())->getValeur();
    }
    else {
    	cout << "N'a pas ecris" << endl;
    }
    valeur = expression->getValeur(); // on évalue l'expression
    return valeur; // par convention, une affectation a pour valeur la valeur affectée
}

////////////////////////////////////////////////////////////////////////////////
// void NoeudEcrire::afficher(unsigned short indentation) {
//   Noeud::afficher(indentation);
//   cout << "Noeud - Ecrire" << endl;
//   expression->afficher(indentation+1); // on affiche l'expression a ecrire en augmentant l'indentation
// }

void NoeudEcrire::Accept (NoeudVisitor& visitor) {
    if (typeid(visitor) == typeid(AfficherVisitor)) {
        visitor.IncresIndentation();
		visitor.VisitNoeudEcrire(this);
		expression->Accept(visitor);
        visitor.DecresIndentation();
    }
    else {
      	expression->Accept(visitor);
	visitor.VisitNoeudEcrire(this);
    }
}



////////////////////////////////////////////////////////////////////////////////
// NoeudOperateurBinaire
////////////////////////////////////////////////////////////////////////////////

NoeudOperateurBinaire::NoeudOperateurBinaire ( Symbole operateur,
        Noeud* operandeGauche,
        Noeud* operandeDroit) {
    this->operateur=operateur;
    this->operandeGauche=operandeGauche;
    this->operandeDroit=operandeDroit;
}

////////////////////////////////////////////////////////////////////////////////
Valeur* NoeudOperateurBinaire::getValeur() {
    Valeur* valeur =  new ValeurInt(0);
    Valeur* vog=operandeGauche->getValeur();
    Valeur* vod=operandeDroit->getValeur();

    if (typeid(vog) == typeid(vod) && typeid(*vog) == typeid(ValeurInt)) {
        if      (this->operateur=="+") {
	  valeur = new ValeurInt((((ValeurInt*)vog)->getValeur())+(((ValeurInt*)vod)->getValeur()));}
        else if (this->operateur=="-") valeur = new ValeurInt((((ValeurInt*)vog)->getValeur())-(((ValeurInt*)vod)->getValeur()));
        else if (this->operateur=="*") valeur = new ValeurInt((((ValeurInt*)vog)->getValeur())*(((ValeurInt*)vod)->getValeur()));
        else if (this->operateur=="/") {
            if ((((ValeurInt*)vog)->getValeur())!=0)
                valeur = new ValeurInt((((ValeurInt*)vog)->getValeur())/(((ValeurInt*)vod)->getValeur()));
            else {
                cout << "Erreur pendant l'interpretation : division par zero" << endl;
                exit(0); // plus tard on levera une exception
            }
        }
    }
    else if (typeid(vog) == typeid(vod) && typeid(*vog) == typeid(ValeurFloat)) {
        if      (this->operateur=="+") valeur = new ValeurFloat((((ValeurFloat*)vog)->getValeur())+(((ValeurFloat*)vod)->getValeur()));
        else if (this->operateur=="-") valeur = new ValeurFloat((((ValeurFloat*)vog)->getValeur())-(((ValeurFloat*)vod)->getValeur()));
        else if (this->operateur=="*") valeur = new ValeurFloat((((ValeurFloat*)vog)->getValeur())*(((ValeurFloat*)vod)->getValeur()));
        else if (this->operateur=="/") {
            if ((((ValeurFloat*)vog)->getValeur())!=0.0)
                valeur = new ValeurFloat((((ValeurFloat*)vog)->getValeur())/(((ValeurFloat*)vod)->getValeur()));
            else {
                cout << "Erreur pendant l'interpretation : division par zero" << endl;
                exit(0); // plus tard on levera une exception
            }
        }
    }
    if ((this->operateur=="et") || (this->operateur=="ou")){
    	cout << "opration boole" << endl;
        bool bog = 1;
        bool bod = 1;
        if ((typeid(*vog) == typeid(ValeurInt)) && ((((ValeurInt*)vog)->getValeur())==0))
            bog = 0;
        if ((typeid(*vod) == typeid(ValeurInt)) && ((((ValeurInt*)vod)->getValeur())==0))
            bod = 0;
        if ((typeid(*vog) == typeid(ValeurFloat)) && ((((ValeurFloat*)vog)->getValeur())==0.0))
            bog = 0;
        if ((typeid(*vod) == typeid(ValeurFloat)) && ((((ValeurFloat*)vod)->getValeur())==0.0))
            bod = 0;
        if ((typeid(*vog) == typeid(ValeurString)) && ((((ValeurString*)vog)->getValeur())=="'\0'"))
            bog = 0;
        if ((typeid(*vod) == typeid(ValeurString)) && ((((ValeurString*)vod)->getValeur())=="'\0'"))
            bod = 0;
//         if ((typeid(vog) == typeid(char)) && ((((ValeurChar*)vog)->getValeur())=='\0'))
//             bog = 0;
//         if ((typeid(vod) == typeid(char)) && ((((ValeurChar*)vod)->getValeur())=='\0'))
//             bog = 0;
        if (this->operateur=="et") {
            if (bog==0) valeur = new ValeurInt(0);
            else {
                if (bod==1) valeur = new ValeurInt(1);
            }
        }
        else { // ou
        	cout << "opration boole" << endl;
            if (bog==1) valeur = new ValeurInt(1);
            else {
                if (bod==0) valeur = new ValeurInt(0);
            }
        }
    }

    if (this->operateur=="!"){
    	cout << "opration boole" << endl;
        bool bod = 1;
        if ((typeid(*vod) == typeid(ValeurInt)) && ((((ValeurInt*)vod)->getValeur())==0))
            bod = 0;
        if ((typeid(*vod) == typeid(ValeurFloat)) && ((((ValeurFloat*)vod)->getValeur())==0.0))
            bod = 0;
        if ((typeid(*vod) == typeid(ValeurString)) && ((((ValeurString*)vod)->getValeur())=="'\0'"))
        	bod = 0;
		if (bod==1) valeur = new ValeurInt(0);
		else 	valeur = new ValeurInt(1);
    }

	 if (typeid(*vog) == typeid(ValeurInt)) {
		 if ((this->operateur=="==") && (((ValeurInt*)vog)->getValeur() == ((ValeurInt*)vod)->getValeur())) {
				 valeur = new ValeurInt(1);
		 }
		 if ((this->operateur=="!=") && (((ValeurInt*)vog)->getValeur() != ((ValeurInt*)vod)->getValeur())) {
				 valeur = new ValeurInt(1);
		 }
		 if ((this->operateur=="<=") && (((ValeurInt*)vog)->getValeur() <= ((ValeurInt*)vod)->getValeur())) {
				 valeur = new ValeurInt(1);
		 }
		 if ((this->operateur=="<") && (((ValeurInt*)vog)->getValeur() < ((ValeurInt*)vod)->getValeur())) {
				 valeur = new ValeurInt(1);
		 }
		 if ((this->operateur==">=") && (((ValeurInt*)vog)->getValeur() >= ((ValeurInt*)vod)->getValeur())) {
				 valeur = new ValeurInt(1);
		 }
		 if ((this->operateur==">") && (((ValeurInt*)vog)->getValeur() > ((ValeurInt*)vod)->getValeur())) {
				 valeur = new ValeurInt(1);
		 }
     }
	 else if (typeid(*vog) == typeid(ValeurFloat)) {
		 if ((this->operateur=="==") && (((ValeurFloat*)vog)->getValeur() == ((ValeurFloat*)vod)->getValeur())) {
				 valeur = new ValeurInt(1);
		 }
		 if ((this->operateur=="!=") && (((ValeurFloat*)vog)->getValeur() != ((ValeurFloat*)vod)->getValeur())) {
				 valeur = new ValeurInt(1);
		 }
		 if ((this->operateur=="<=") && (((ValeurFloat*)vog)->getValeur() <= ((ValeurFloat*)vod)->getValeur())) {
				 valeur = new ValeurInt(1);
		 }
		 if ((this->operateur=="<") && (((ValeurFloat*)vog)->getValeur() < ((ValeurFloat*)vod)->getValeur())) {
				 valeur = new ValeurInt(1);
		 }
		 if ((this->operateur==">=") && (((ValeurFloat*)vog)->getValeur() >= ((ValeurFloat*)vod)->getValeur())) {
				 valeur = new ValeurInt(1);
		 }
		 if ((this->operateur==">") && (((ValeurFloat*)vog)->getValeur() > ((ValeurFloat*)vod)->getValeur())) {
				 valeur = new ValeurInt(1);
		 }
	 }
	 else if (typeid(*vog) == typeid(ValeurString)) {
		 if ((this->operateur=="==") && (((ValeurString*)vog)->getValeur() == ((ValeurString*)vod)->getValeur())) {
				 valeur = new ValeurInt(1);
		 }
		 if ((this->operateur=="!=") && (((ValeurString*)vog)->getValeur() != ((ValeurString*)vod)->getValeur())) {
				 valeur = new ValeurInt(1);
		 }
		 if ((this->operateur=="<=") && (((ValeurString*)vog)->getValeur() <= ((ValeurString*)vod)->getValeur())) {
				 valeur = new ValeurInt(1);
		 }
		 if ((this->operateur=="<") && (((ValeurString*)vog)->getValeur() < ((ValeurString*)vod)->getValeur())) {
				 valeur = new ValeurInt(1);
		 }
		 if ((this->operateur==">=") && (((ValeurString*)vog)->getValeur() >= ((ValeurString*)vod)->getValeur())) {
				 valeur = new ValeurInt(1);
		 }
		 if ((this->operateur==">") && (((ValeurString*)vog)->getValeur() > ((ValeurString*)vod)->getValeur())) {
				 valeur = new ValeurInt(1);
		 }
	 }







  /*   else if (this->operateur=="==") {


         if (og == od) valeur = new ValeurInt(1);
     }
     else if (this->operateur=="!=") {
         if (og != od) valeur = new ValeurInt(1);
     }
     else if (this->operateur=="<") {
         if (og < od) valeur = new ValeurInt(1);
     }
     else if (this->operateur=="<=") {
         if (og <= od) valeur = new ValeurInt(1);
     }
     else if (this->operateur==">") {
         if (og > od) valeur = new ValeurInt(1);
     }
     else if (this->operateur==">=") {
         if (og >= od)valeur = new ValeurInt(1);
     }
     else if (this->operateur=="!") {
         if (od == 0) valeur = new ValeurInt(1);
     }*/

   /* if (typeid(operandeGauche) == typeid(int)) int og = ((ValeurInt*)operandeGauche->getValeur())->getValeur();
    else if (typeid(operandeGauche) == typeid(float)) float og = ((ValeurFloat*)operandeGauche->getValeur())->getValeur();
    else if (typeid(operandeGauche) == typeid(string)) string og = ((ValeurString*)operandeGauche->getValeur())->getValeur();
    else if (typeid(operandeGauche) == typeid(char)) char og = ((ValeurChar*)operandeGauche->getValeur())->getValeur();
    else {  int og = 0;}
    if (typeid(operandeGauche) == typeid(int)) int od = ((ValeurInt*)operandeDroit->getValeur())->getValeur();
    else if (typeid(operandeDroit) == typeid(float)) float od = ((ValeurFloat*)operandeDroit->getValeur())->getValeur();
    else if (typeid(operandeDroit) == typeid(string)) string od = ((ValeurString*)operandeDroit->getValeur())->getValeur();
    else if (typeid(operandeDroit) == typeid(char)) char od = ((ValeurChar*)operandeDroit->getValeur())->getValeur();
    else { int od = 0;}*/
//   og=operandeGauche->getValeur();
    //  od=operandeDroit->getValeur();
    /*    if ((typeid(operandeGauche->getValeur()) == typeid(operandeDroit->getValeur())) && ((typeid(operandeGauche->getValeur()) == typeid(ValeurInt*)))) {
    		if      (this->operateur=="+") valeur = new ValeurInt((((ValeurInt*)operandeGauche->getValeur())->getValeur())+(((ValeurInt*)operandeDroit->getValeur())->getValeur()));
    		else if (this->operateur=="-") valeur = new ValeurInt((((ValeurInt*)operandeGauche->getValeur())->getValeur())-(((ValeurInt*)operandeDroit->getValeur())->getValeur()));
    		else if (this->operateur=="*") valeur = new ValeurInt((((ValeurInt*)operandeGauche->getValeur())->getValeur())*(((ValeurInt*)operandeDroit->getValeur())->getValeur()));
    		else if (this->operateur=="/") {
    			if (((ValeurInt*)operandeDroit->getValeur())->getValeur()==0)
    				valeur = new ValeurInt((((ValeurInt*)operandeGauche->getValeur())->getValeur())/(((ValeurInt*)operandeDroit->getValeur())->getValeur()));
    			else {
    				cout << "Erreur pendant l'interpretation : division par zero" << endl;
    				exit(0); // plus tard on levera une exception
    			}
    		}
        }
        else if ((typeid(operandeGauche->getValeur()) == typeid(operandeDroit->getValeur())) && ((typeid(operandeGauche->getValeur()) == typeid(ValeurFloat*)))) {
    		if      (this->operateur=="+") valeur = new ValeurFloat((((ValeurFloat*)operandeGauche->getValeur())->getValeur())+(((ValeurFloat*)operandeDroit->getValeur())->getValeur()));
    		else if (this->operateur=="-") valeur = new ValeurFloat((((ValeurFloat*)operandeGauche->getValeur())->getValeur())-(((ValeurFloat*)operandeDroit->getValeur())->getValeur()));
    		else if (this->operateur=="*") valeur = new ValeurFloat((((ValeurFloat*)operandeGauche->getValeur())->getValeur())*(((ValeurFloat*)operandeDroit->getValeur())->getValeur()));
    		else if (this->operateur=="/") {
    			if (((ValeurFloat*)operandeDroit->getValeur())->getValeur()==0.0)
    				valeur = new ValeurFloat((((ValeurFloat*)operandeGauche->getValeur())->getValeur())/(((ValeurFloat*)operandeDroit->getValeur())->getValeur()));
    			else {
    				cout << "Erreur pendant l'interpretation : division par zero" << endl;
    				exit(0); // plus tard on levera une exception
    			}
    		}
        }*/
    /*  else if ((typeid(od) == typeid(og)) && ((typeid(od) == typeid(int)))) {
      	if      (this->operateur=="+") valeur = new ValeurFloat(og+od);
      	else if (this->operateur=="-") valeur = new ValeurFloat(og-od);
      	else if (this->operateur=="*") valeur = new ValeurFloat(og*od);
      	else if (this->operateur=="/") {
      		if (od=0.0)
      			valeur = new ValeurFloat(og/od);
      		else {
      			cout << "Erreur pendant l'interpretation : division par zero" << endl;
      			exit(0); // plus tard on levera une exception
      		}
      	}
      }*/
    /*   else if (this->operateur=="+" || this->operateur=="-" || this->operateur=="*" || this->operateur=="/") {
       	cout << "Erreur pendant l'interpretation : type" << endl;
       	exit(0); // plus tard on levera une exception
       }
       else {
       	if (this->operateur=="et") {
       		if (typeid(operandeGauche->getValeur()) == typeid(int))
       			if ((((ValeurFloat*)operandeGauche->getValeur())->getValeur())==0) valeur = new ValeurInt(0);
       			else {
       	    		if (typeid(operandeDroit->getValeur()) == typeid(int))
       	    			if ((((ValeurFloat*)operandeDroit->getValeur())->getValeur())|=0) valeur = new ValeurInt(1);
       	    		else if (typeid(operandeDroit->getValeur()) == typeid(float))
       	    			if ((((ValeurFloat*)operandeDroit->getValeur())->getValeur())|=0.0) valeur = new ValeurInt(1);
       	    		else if (typeid(operandeDroit->getValeur()) == typeid(string))
       	    			if ((((ValeurFloat*)operandeDroit->getValeur())->getValeur())|="\0") valeur = new ValeurInt(1);
       	    		else if (typeid(operandeDroit->getValeur()) == typeid(char))
       	    			if ((((ValeurFloat*)operandeDroit->getValeur())->getValeur())|='\0') valeur = new ValeurInt(1);
       			}
       		if (typeid(operandeGauche->getValeur()) == typeid(float))
       			if ((((ValeurFloat*)operandeGauche->getValeur())->getValeur())==0.0) valeur = new ValeurInt(0);
       			else {
       				if (typeid(operandeDroit->getValeur()) == typeid(int))
       					if ((((ValeurFloat*)operandeDroit->getValeur())->getValeur())|=0) valeur = new ValeurInt(1);
       				else if (typeid(operandeDroit->getValeur()) == typeid(float))
       					if ((((ValeurFloat*)operandeDroit->getValeur())->getValeur())|=0.0) valeur = new ValeurInt(1);
       				else if (typeid(operandeDroit->getValeur()) == typeid(string))
       					if ((((ValeurFloat*)operandeDroit->getValeur())->getValeur())|="\0") valeur = new ValeurInt(1);
       				else if (typeid(operandeDroit->getValeur()) == typeid(char))
       					if ((((ValeurFloat*)operandeDroit->getValeur())->getValeur())|='\0') valeur = new ValeurInt(1);
       			}
       		if (typeid(operandeGauche->getValeur()) == typeid(string))
       			if ((((ValeurFloat*)operandeGauche->getValeur())->getValeur())=="\0") valeur = new ValeurInt(0);
       			else {
       				if (typeid(operandeDroit->getValeur()) == typeid(int))
       					if ((((ValeurFloat*)operandeDroit->getValeur())->getValeur())|=0) valeur = new ValeurInt(1);
       				else if (typeid(operandeDroit->getValeur()) == typeid(float))
       					if ((((ValeurFloat*)operandeDroit->getValeur())->getValeur())|=0.0) valeur = new ValeurInt(1);
       				else if (typeid(operandeDroit->getValeur()) == typeid(string))
       					if ((((ValeurFloat*)operandeDroit->getValeur())->getValeur())|="\0") valeur = new ValeurInt(1);
       				else if (typeid(operandeDroit->getValeur()) == typeid(char))
       					if ((((ValeurFloat*)operandeDroit->getValeur())->getValeur())|='\0') valeur = new ValeurInt(1);
       			}
       		if (typeid(operandeGauche->getValeur()) == typeid(char))
       			if ((((ValeurFloat*)operandeGauche->getValeur())->getValeur())=='\0') valeur = new ValeurInt(0);
       			else {
       				if (typeid(operandeDroit->getValeur()) == typeid(int))
       					if ((((ValeurFloat*)operandeDroit->getValeur())->getValeur())|=0) valeur = new ValeurInt(1);
       				else if (typeid(operandeDroit->getValeur()) == typeid(float))
       					if ((((ValeurFloat*)operandeDroit->getValeur())->getValeur())|=0.0) valeur = new ValeurInt(1);
       				else if (typeid(operandeDroit->getValeur()) == typeid(string))
       					if ((((ValeurFloat*)operandeDroit->getValeur())->getValeur())|="\0") valeur = new ValeurInt(1);
       				else if (typeid(operandeDroit->getValeur()) == typeid(char))
       					if ((((ValeurFloat*)operandeDroit->getValeur())->getValeur())|='\0') valeur = new ValeurInt(1);
       			}
       	}
       	if (this->operateur=="ou") {
       		if (typeid(operandeGauche->getValeur()) == typeid(int))
       			if ((((ValeurFloat*)operandeGauche->getValeur())->getValeur())|=0) valeur = new ValeurInt(1);
       			else {
       				if (typeid(operandeDroit->getValeur()) == typeid(int))
       					if ((((ValeurFloat*)operandeDroit->getValeur())->getValeur())==0) valeur = new ValeurInt(0);
       				else if (typeid(operandeDroit->getValeur()) == typeid(float))
       					if ((((ValeurFloat*)operandeDroit->getValeur())->getValeur())==0.0) valeur = new ValeurInt(0);
       				else if (typeid(operandeDroit->getValeur()) == typeid(string))
       					if ((((ValeurFloat*)operandeDroit->getValeur())->getValeur())=="\0") valeur = new ValeurInt(0);
       				else if (typeid(operandeDroit->getValeur()) == typeid(char))
       					if ((((ValeurFloat*)operandeDroit->getValeur())->getValeur())=='\0') valeur = new ValeurInt(0);
       			}
       		if(typeid(operandeGauche->getValeur()) == typeid(float))
       			if ((((ValeurFloat*)operandeGauche->getValeur())->getValeur())|=0.0) valeur = new ValeurInt(1);
       			else {
       				if (typeid(operandeDroit->getValeur()) == typeid(int))
       					if ((((ValeurFloat*)operandeDroit->getValeur())->getValeur())==0) valeur = new ValeurInt(0);
       				else if (typeid(operandeDroit->getValeur()) == typeid(float))
       					if ((((ValeurFloat*)operandeDroit->getValeur())->getValeur())==0.0) valeur = new ValeurInt(0);
       				else if (typeid(operandeDroit->getValeur()) == typeid(string))
       					if ((((ValeurFloat*)operandeDroit->getValeur())->getValeur())=="\0") valeur = new ValeurInt(0);
       				else if (typeid(operandeDroit->getValeur()) == typeid(char))
       					if ((((ValeurFloat*)operandeDroit->getValeur())->getValeur())=='\0') valeur = new ValeurInt(0);
       			}
       		if (typeid(operandeGauche->getValeur()) == typeid(string))
       			if ((((ValeurFloat*)operandeGauche->getValeur())->getValeur())|="\0") valeur = new ValeurInt(1);
       			else {
       				if (typeid(operandeDroit->getValeur()) == typeid(int))
       					if ((((ValeurFloat*)operandeDroit->getValeur())->getValeur())==0) valeur = new ValeurInt(0);
       				else if (typeid(operandeDroit->getValeur()) == typeid(float))
       					if ((((ValeurFloat*)operandeDroit->getValeur())->getValeur())==0.0) valeur = new ValeurInt(0);
       				else if (typeid(operandeDroit->getValeur()) == typeid(string))
       					if ((((ValeurFloat*)operandeDroit->getValeur())->getValeur())=="\0") valeur = new ValeurInt(0);
       				else if (typeid(operandeDroit->getValeur()) == typeid(char))
       					if ((((ValeurFloat*)operandeDroit->getValeur())->getValeur())=='\0') valeur = new ValeurInt(0);
       			}
       		if (typeid(operandeGauche->getValeur()) == typeid(char))
       			if ((((ValeurFloat*)operandeGauche->getValeur())->getValeur())|='\0') valeur = new ValeurInt(1);
       			else {
       				if (typeid(operandeDroit->getValeur()) == typeid(int))
       					if ((((ValeurFloat*)operandeDroit->getValeur())->getValeur())==0) valeur = new ValeurInt(0);
       				else if (typeid(operandeDroit->getValeur()) == typeid(float))
       					if ((((ValeurFloat*)operandeDroit->getValeur())->getValeur())==0.0) valeur = new ValeurInt(0);
       				else if (typeid(operandeDroit->getValeur()) == typeid(string))
       					if ((((ValeurFloat*)operandeDroit->getValeur())->getValeur())=="\0") valeur = new ValeurInt(0);
       				else if (typeid(operandeDroit->getValeur()) == typeid(char))
       					if ((((ValeurFloat*)operandeDroit->getValeur())->getValeur())=='\0') valeur = new ValeurInt(0);
       			}
       	}*/
    /*else if (this->operateur=="ou") {
    	if (og==1) valeur = 1;
    	else {
    		if (od==0) valeur = 0;
    	}
    }*/
    /*	if (this->operateur=="==") {
    		if ((((ValeurFloat*)operandeGauche->getValeur())->getValeur()) == (((ValeurFloat*)operandeDroit->getValeur())->getValeur())) valeur = new ValeurInt(1);
    	}
    	else if (this->operateur=="!=") {
    		if ((((ValeurFloat*)operandeGauche->getValeur())->getValeur()) != (((ValeurFloat*)operandeDroit->getValeur())->getValeur())) valeur = new ValeurInt(1);
    	}
    	else if (this->operateur=="<") {
    		if ((((ValeurFloat*)operandeGauche->getValeur())->getValeur()) < (((ValeurFloat*)operandeDroit->getValeur())->getValeur())) valeur = new ValeurInt(1);
    	}
    	else if (this->operateur=="<=") {
    		if ((((ValeurFloat*)operandeGauche->getValeur())->getValeur()) <= (((ValeurFloat*)operandeDroit->getValeur())->getValeur())) valeur = new ValeurInt(1);
    	}
    	else if (this->operateur==">") {
    		if ((((ValeurFloat*)operandeGauche->getValeur())->getValeur()) > (((ValeurFloat*)operandeDroit->getValeur())->getValeur())) valeur = new ValeurInt(1);
    	}
    	else if (this->operateur==">=") {
    		if ((((ValeurFloat*)operandeGauche->getValeur())->getValeur()) >= (((ValeurFloat*)operandeDroit->getValeur())->getValeur())) valeur = new ValeurInt(1);
    	}
    	else if (this->operateur=="!") {
    		if (typeid(operandeDroit->getValeur()) == typeid(int))
    			if ((((ValeurFloat*)operandeDroit->getValeur())->getValeur())==0) valeur = new ValeurInt(1);
    		else if (typeid(operandeDroit->getValeur()) == typeid(float))
    			if ((((ValeurFloat*)operandeDroit->getValeur())->getValeur())==0.0) valeur = new ValeurInt(1);
    		else if (typeid(operandeDroit->getValeur()) == typeid(string))
    			if ((((ValeurFloat*)operandeDroit->getValeur())->getValeur())=="\0") valeur = new ValeurInt(1);
    		else if (typeid(operandeDroit->getValeur()) == typeid(char))
    			if ((((ValeurFloat*)operandeDroit->getValeur())->getValeur())=='\0') valeur = new ValeurInt(1);
    		//if (od == 0) valeur = 1;
    	}
    }*/
    return valeur;
}

////////////////////////////////////////////////////////////////////////////////
// void NoeudOperateurBinaire::afficher(unsigned short indentation) {
//   Noeud::afficher(indentation);
//   cout << "Noeud - Operateur Binaire \"" << this->operateur.getChaine() << "\" applique a : " << endl;
//   operandeGauche->afficher(indentation+1);  // on affiche fils gauche et fils droit
//   operandeDroit->afficher(indentation+1);   // en augmentant l'indentation
// }

void NoeudOperateurBinaire::Accept (NoeudVisitor& visitor) {
    if (typeid(visitor) == typeid(AfficherVisitor)) {
        visitor.IncresIndentation();
		visitor.VisitNoeudOperateurBinaire(this);
		operandeGauche->Accept(visitor);
		operandeDroit->Accept(visitor);
        visitor.DecresIndentation();
    }
    else {
	operandeGauche->Accept(visitor);
	operandeDroit->Accept(visitor);
	visitor.VisitNoeudOperateurBinaire(this);
    }
}
